home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / tptc16.zip / TPCSTMT.INC < prev    next >
Text File  |  1993-01-04  |  16KB  |  854 lines

  1.  
  2. (*
  3.  * TPTC - Turbo Pascal to C translator
  4.  *
  5.  * (C) 1988 Samuel H. Smith (rev. 13-Feb-88)
  6.  *
  7.  *)
  8.  
  9. (********************************************************************)
  10. (*
  11.  * control statement processors
  12.  *    for, while, repeat, with, idents
  13.  *
  14.  * all expect tok to be keyword
  15.  * all exit at end of statement with ltok as ; or end
  16.  *
  17.  *)
  18.  
  19. procedure pfor;
  20. var
  21.    up:       boolean;
  22.    id:       string80;
  23.    low,high: string80;
  24.  
  25. begin
  26.    write(ofd[level],'for (');
  27.    gettok;   {consume the FOR}
  28.  
  29.    id := plvalue;
  30.    gettok;   {consume the :=}
  31.  
  32.    low := pexpr;
  33.  
  34.    if tok = 'TO' then
  35.       up := true
  36.    else
  37.  
  38.    if tok = 'DOWNTO' then
  39.       up := false
  40.    else
  41.  
  42.    begin
  43.       syntax('TO or DOWNTO expected (pfor)');
  44.       exit;
  45.    end;
  46.  
  47.    gettok;
  48.    high := pexpr;
  49.  
  50.    if up then
  51.       write(ofd[level],id,' = ',low,'; ',id,' <= ',high,'; ',id,'++) ')
  52.    else
  53.       write(ofd[level],id,' = ',low,'; ',id,' >= ',high,'; ',id,'--) ');
  54.  
  55.    gettok;   {consume the DO}
  56.    pstatement;
  57. end;
  58.  
  59.  
  60. (********************************************************************)
  61. procedure pwhile;
  62. var
  63.    cond: string255;
  64.  
  65. begin
  66.    gettok;   {consume the WHILE}
  67.  
  68.    cond := pexpr;
  69.    write(ofd[level],'while (',cond,') ');
  70.  
  71.    gettok;   {consume the DO}
  72.    pstatement;
  73. end;
  74.  
  75.  
  76. (********************************************************************)
  77. procedure pwith;
  78. var
  79.    prefix: string80;
  80.  
  81. begin
  82.    write(ofd[level],'/* with ');
  83.  
  84.    gettok;   {consume the DO}
  85.    prefix := plvalue;
  86.  
  87.    write(ofd[level],prefix,' DO */ ');
  88.    gettok;   {consume the DO}
  89.    pstatement;
  90.  
  91.    write(ofd[level],' /* end with */');
  92.    newline;
  93. end;
  94.  
  95.  
  96. (********************************************************************)
  97. procedure prepeat;
  98. var
  99.    cond: string255;
  100.  
  101. begin
  102.    write(ofd[level],'do { ');
  103.    gettok;
  104.  
  105.    while tok <> 'UNTIL' do
  106.    begin
  107.       pstatement;
  108.  
  109.       if tok = ';' then
  110.       begin
  111.          puttok;
  112.          gettok;
  113.       end;
  114.    end;
  115.  
  116.    gettok;
  117.    cond := pexpr;
  118.  
  119.    write(ofd[level],'}  while (!(', cond, ')) ');
  120. end;
  121.  
  122.  
  123. (********************************************************************)
  124. procedure pcase;
  125. var
  126.    ex: string255;
  127.    i:  integer;
  128.    c:  char;
  129.  
  130. begin
  131.    gettok;
  132.    ex := pexpr;
  133.    write(ofd[level],'switch (',ex,') {');
  134.  
  135.    gettok;   {consume the OF}
  136.  
  137.    while (tok <> '}') and (tok <> 'ELSE') do
  138.    begin
  139.  
  140.       repeat
  141.          if tok = ',' then
  142.             gettok;
  143.  
  144.          if tok = '..' then
  145.          begin
  146.             i := atoi(ex);
  147.             if i = 0 then
  148.                c := ex[2];
  149.  
  150.             gettok;
  151.             ex := pexpr;
  152.             if i=0 then
  153.                for c := succ(c) to ex[2] do
  154.                begin
  155.                   newline;
  156.                   write(ofd[level],'case ''',c,''':   ');
  157.                end
  158.             else
  159.                for i := succ(i) to atoi(ex) do
  160.                begin
  161.                   newline;
  162.                   write(ofd[level],'case ',i,':    ');
  163.                end;
  164.  
  165.          end
  166.          else
  167.          begin
  168.             ex := pexpr;
  169.             newline;
  170.             write(ofd[level],'case ',ex,':   ');
  171.          end;
  172.  
  173.       until tok = ':';
  174.       gettok;
  175.  
  176.       pstatement;
  177.       write(ofd[level],'break; ');
  178.       newline;
  179.  
  180.       if tok = ';' then
  181.          gettok;
  182.    end;
  183.  
  184.    if tok = 'ELSE' then
  185.    begin
  186.       newline;
  187.       write(ofd[level],'default: ');
  188.       gettok;   {consume the else}
  189.  
  190.       while tok <> '}' do
  191.       begin
  192.          pstatement;
  193.          if tok = ';' then
  194.             gettok;
  195.       end;
  196.    end;
  197.  
  198.    puttok;
  199.    gettok;
  200.  
  201.    if tok = ';' then
  202.       gettok;
  203. end;
  204.  
  205.  
  206. (********************************************************************)
  207. procedure pif;
  208. var
  209.    cond: string255;
  210. begin
  211.    gettok;   {consume the IF}
  212.  
  213.    cond := pexpr;
  214.    write(ofd[level],'if (', cond, ') ');
  215.  
  216.    gettok;   {consume the THEN}
  217.    pstatement;
  218.  
  219.    if tok = 'ELSE' then
  220.    begin
  221.       write(ofd[level],'else ');
  222.       gettok;
  223.       if tok <> '}' then
  224.          pstatement;
  225.    end;
  226.  
  227. end;
  228.  
  229.  
  230. (********************************************************************)
  231. procedure pexit;
  232. begin
  233.    write(ofd[level],'return;');
  234.  
  235.    gettok;
  236.    if tok = ';' then
  237.       gettok;
  238. end;
  239.  
  240.  
  241. (********************************************************************)
  242. procedure pgoto;
  243. var
  244.    ex:  anystring;
  245.  
  246. begin
  247.    gettok;                      {consume the goto}
  248.  
  249.    if toktype = number then
  250.       ltok := 'label_' + ltok;  {modify numeric labels}
  251.  
  252.    write(ofd[level],'goto ',ltok,';');
  253.  
  254.    gettok;                      {consume the label}
  255.  
  256.    if tok = ';' then
  257.       gettok;
  258. end;
  259.  
  260.  
  261. (********************************************************************)
  262. procedure phalt;
  263. var
  264.    ex: anystring;
  265.  
  266. begin
  267.    gettok;
  268.  
  269.    if tok = '(' then
  270.    begin
  271.       gettok;
  272.       ex := pexpr;
  273.       gettok;
  274.    end
  275.    else
  276.       ex := '0';     {default exit expression}
  277.  
  278.  
  279.    write(ofd[level],'exit(',ex,')',';');
  280.  
  281.    if tok = ';' then
  282.       gettok;
  283. end;
  284.  
  285.  
  286. (********************************************************************)
  287. procedure pread;
  288. var
  289.    ctl:  anystring;
  290.    func: anystring;
  291.    ex:   paramlist;
  292.    ty:   paramlist;
  293.    w:    anystring;
  294.    n:    anystring;
  295.    ln:   boolean;
  296.    i:    integer;
  297.    sym:  symptr;
  298.  
  299. begin
  300.    nospace := true;   {don't copy source whitespace to output during
  301.                        this processing.  this prevents spaces from
  302.                        getting moved around}
  303.  
  304.    ln := tok = 'READLN';
  305.    nospace := true;
  306.    func := 'scanv(';
  307.  
  308.    gettok;   {consume the write}
  309.  
  310.    if tok = '(' then
  311.    begin
  312.       gettok;
  313.  
  314.       if ltok = '[' then   {check for MT+ [addr(name)], form}
  315.       begin
  316.          gettok;   {consume the '[' }
  317.  
  318.          if tok = ']' then
  319.             func := 'scanf('
  320.          else
  321.  
  322.          begin
  323.             gettok;   {consume the ADDR}
  324.             gettok;   {consume the '(' }
  325.  
  326.             func := 'fiscanf(' + usetok + ',';
  327.  
  328.             gettok;   {consume the ')'}
  329.          end;
  330.  
  331.          gettok;   {consume the ']'}
  332.          if tok = ',' then
  333.             gettok;
  334.       end
  335.       else
  336.  
  337.       begin
  338.          sym := locatesym(ltok);   {check for file variables}
  339.          if sym <> nil then
  340.          begin
  341.             if sym^.symtype = s_file then
  342.             begin
  343.                func := 'fscanv(' + usetok + ',';
  344.                if tok = ',' then
  345.                   gettok;
  346.             end;
  347.          end;
  348.       end;
  349.  
  350.       ctl := '';
  351.       ex.n := 0;
  352.  
  353.       while tok <> ')' do
  354.       begin
  355.          inc(ex.n);
  356.          ex.id[ex.n] := pexpr;
  357.          ty.id[ex.n] := exprtype(ex.id[ex.n]);
  358.  
  359.          ctl := ctl + '%'+ty.id[ex.n];
  360.          if tok = ',' then
  361.             gettok;
  362.       end;
  363.  
  364.       gettok;   {consume the )}
  365.  
  366.       if ctl = '%s' then
  367.          ctl := '#';
  368.       if ln then
  369.          ctl := ctl + '\n';
  370.  
  371.       if func[1] <> 'f' then
  372.          func := 'f' + func + 'stdin,';
  373.  
  374.       write(ofd[level],func,'"',ctl,'"');
  375.       for i := 1 to ex.n do
  376.          if ty.id[i] <> 's' then
  377.             write(ofd[level],',&',ex.id[i])
  378.          else
  379.             write(ofd[level],',',ex.id[i]);
  380.  
  381.       write(ofd[level],')');
  382.    end
  383.  
  384.    else   {otherwise there is no param list}
  385.       if ln then
  386.          write(ofd[level],'scanf("\n")');
  387.  
  388.    nospace := false;
  389.  
  390.    if tok = ';' then
  391.    begin
  392.       puttok;
  393.       gettok;
  394.    end
  395.    else
  396.  
  397.    begin
  398.       write(ofd[level],'; ');
  399.       newline;
  400.    end;
  401.  
  402. end;
  403.  
  404.  
  405. (********************************************************************)
  406. procedure pwrite;
  407. var
  408.    ctl:  anystring;
  409.    func: anystring;
  410.    ex:   paramlist;
  411.    w:    anystring;
  412.    n:    anystring;
  413.    p:    string255;
  414.    ln:   boolean;
  415.    ty:   string[2];
  416.    i:    integer;
  417.  
  418. begin
  419.    nospace := true;   {don't copy source whitespace to output during
  420.                        this processing.  this prevents spaces from
  421.                        getting moved around}
  422.  
  423.    ln := tok = 'WRITELN';
  424.    nospace := true;
  425.    func := 'printf(';
  426.  
  427.    gettok;   {consume the write}
  428.  
  429.    if tok = '(' then
  430.    begin
  431.       gettok;   {consume the (}
  432.  
  433.       ctl := '';
  434.       ex.n := 0;
  435.  
  436.       while tok <> ')' do
  437.       begin
  438.          p := pexpr;
  439.  
  440.          if (ex.n = 0) and (curtype = s_file) then
  441.          begin
  442.             func := 'fprintf(' + p + ',';
  443.          end
  444.          else
  445.  
  446.          begin
  447.             inc(ex.n);
  448.             ex.id[ex.n] := p;
  449.             ty := exprtype(p);
  450.             if ty = 'D' then
  451.                ty := 'ld';
  452.  
  453.             w := '';
  454.             n := '';
  455.             if tok = ':' then
  456.             begin
  457.                gettok;
  458.                w := pexpr;
  459.  
  460.                if tok = ':' then
  461.                begin
  462.                   gettok;
  463.                   n := pexpr;
  464.                   ctl := ctl + '%'+w+'.'+n+'f';
  465.                end
  466.                else
  467.                   ctl := ctl + '%'+w+ty;
  468.             end
  469.             else
  470.  
  471.             begin
  472.                {pass literals into the control string}
  473.                if (p[1] = '"') or (p[1] = '''') then
  474.                begin
  475.                   ctl := ctl + copy(p,2,length(p)-2);
  476.                   dec(ex.n);
  477.                end
  478.  
  479.                {otherwise put in the control string for this param}
  480.                else
  481.                   ctl := ctl + '%'+ty;
  482.             end;
  483.          end;
  484.  
  485.          if tok = ',' then
  486.             gettok;
  487.       end;
  488.  
  489.       gettok;   {consume the )}
  490.  
  491.       if ln then
  492.          ctl := ctl + '\n';
  493.  
  494.       write(ofd[level],func,'"',ctl,'"');
  495.       for i := 1 to ex.n do
  496.          write(ofd[level],',',ex.id[i]);
  497.  
  498.       write(ofd[level],')');
  499.    end
  500.  
  501.    else   {otherwise there is no param list}
  502.       if ln then
  503.          write(ofd[level],'printf("\n")');
  504.  
  505.    nospace := false;
  506.  
  507.    if tok = ';' then
  508.    begin
  509.       puttok;
  510.       gettok;
  511.    end
  512.    else
  513.  
  514.    begin
  515.       write(ofd[level],'; ');
  516.       newline;
  517.    end;
  518.  
  519. end;
  520.  
  521.  
  522. (********************************************************************)
  523. procedure pnew;
  524. var
  525.    lv: string255;
  526. begin
  527.  
  528.    gettok;   {consume the new}
  529.    gettok;   {consume the (}
  530.    lv := plvalue;
  531.    gettok;   {consume the )}
  532.  
  533.    write(ofd[level],lv,' = malloc(sizeof(*',lv,'));');
  534.  
  535.    if tok = ';' then
  536.       gettok;
  537. end;
  538.  
  539.  
  540. (********************************************************************)
  541. procedure pport(kw: string255);
  542.    {translate port/portw/mem/memw}
  543. var
  544.    lv: string255;
  545.  
  546. begin
  547.    lv := kw + '(';
  548.  
  549.    gettok;     {consume the keyword}
  550.    gettok;     {consume the [ }
  551.  
  552.    repeat
  553.       lv := lv + pexpr;
  554.       if tok = ':' then
  555.       begin
  556.          gettok;
  557.          lv := lv + ',';
  558.       end;
  559.    until tok = ']';
  560.  
  561.    gettok;     {consume the ] }
  562.  
  563.    if tok = ':=' then
  564.    begin
  565.       gettok;       {consume :=, assignment statement}
  566.       lv := lv + ',' + pexpr;
  567.    end;
  568.  
  569.    write(ofd[level],lv,');');
  570.  
  571.    if tok = ';' then
  572.       gettok;
  573. end;
  574.  
  575.  
  576. (********************************************************************)
  577. procedure pinline;
  578.    {translate inline statements}
  579. var
  580.    lv: string255;
  581.  
  582. begin
  583.    gettok;     {consume the keyword}
  584.  
  585.    lv := '';
  586.    while tok <> ')' do
  587.    begin
  588.       gettok;
  589.       if (tok = '/') or (tok = ')') then
  590.       begin
  591.          writeln(ofd[level],'     asm db ',lv,';');
  592.          lv := '';
  593.       end
  594.       else
  595.          lv := lv + ltok + ' ';
  596.    end;
  597.  
  598.    gettok;     {consume the ) }
  599.  
  600.    if tok = ';' then
  601.       gettok;
  602. end;
  603.  
  604.  
  605. (********************************************************************)
  606. procedure pident;
  607.    {parse statements starting with an identifier;  these are either
  608.     assignment statements, function calls, return-value assignments,
  609.     or label identifiers}
  610. var
  611.    ex: string255;
  612.    lv: string255;
  613.    lvt,ext: char;
  614.  
  615. begin
  616.    nospace := true;   {don't copy source whitespace to output during
  617.                        this processing.  this prevents spaces from
  618.                        getting moved around}
  619.    lv := plvalue;
  620.  
  621.    if tok = ':=' then
  622.    begin
  623.       gettok;       {consume :=, assignment statement}
  624.       ex := pexpr;
  625.  
  626.       if iscall(lv) then
  627.          write(ofd[level],'return ',ex)
  628.       else
  629.  
  630.       begin
  631.          lvt := exprtype(lv);
  632.          ext := exprtype(ex);
  633.  
  634.          if copy(ex,1,5) = 'scat(' then
  635.             write(ofd[level],'sbld(', lv,',' , copy(ex,6,255))
  636.          else
  637.  
  638.          if copy(ex,1,5) = 'scat(' then
  639.             write(ofd[level],'sbld(', lv,',' , copy(ex,6,255))
  640.          else
  641.  
  642.          if lvt = 's' then
  643.             if ext = 's' then
  644.                write(ofd[level],'strcpy(',lv,', ',ex,')')
  645.             else
  646.                write(ofd[level],'sbld(',lv,',"%',ext,'",',ex,')')
  647.          else
  648.  
  649.          if lvt = 'c' then
  650.             if ext = 's' then
  651.                write(ofd[level],lv,' = first(',ex,')')
  652.             else
  653.                write(ofd[level],lv,' = ',ex)
  654.          else
  655.             write(ofd[level],lv,' = ',ex);
  656.       end;
  657.    end
  658.    else
  659.  
  660.    if tok = ':' then
  661.    begin
  662.       writeln(ofd[level]);
  663.       write(ofd[level],lv,': ');
  664.  
  665.       gettok;       {label identifier}
  666.  
  667.       if tok = ';' then
  668.          gettok;
  669.  
  670.       exit;
  671.    end
  672.    else
  673.  
  674.    if iscall(lv) then
  675.       write(ofd[level],lv)
  676.    else
  677.       write(ofd[level],lv,'()');
  678.  
  679.    nospace := false;
  680.  
  681.    if tok = ';' then
  682.    begin
  683.       puttok;
  684.       gettok;
  685.    end
  686.    else
  687.  
  688.    begin
  689.       write(ofd[level],'; ');
  690.       newline;
  691.    end;
  692.  
  693. end;
  694.  
  695.  
  696. (********************************************************************)
  697. procedure pnumlabel;
  698.    {parse statements starting with an number;  these must be
  699.     numeric labels}
  700. begin
  701.    writeln(ofd[level]);
  702.    write(ofd[level],'label_',tok,': ');
  703.  
  704.    gettok;      {consume the number}
  705.  
  706.    if tok <> ':' then
  707.    begin
  708.       syntax('":" expected (pnumlabel)');
  709.       exit;
  710.    end;
  711.  
  712.    gettok;      {consume the :}
  713. end;
  714.  
  715.  
  716. (********************************************************************)
  717. (*
  718.  * process single statement
  719.  *
  720.  * expects tok to be first token of statement
  721.  * processes nested blocks
  722.  * exits with tok as end of statement
  723.  *
  724.  *)
  725.  
  726. procedure pstatement;
  727. begin
  728.  
  729.    if tok = ';' then
  730.       begin
  731.          write(ofd[level],'; ');
  732.          gettok;
  733.       end
  734.    else
  735.  
  736.    if tok = '{' then
  737.       pblock
  738.    else
  739.  
  740.    if tok = 'FOR' then
  741.       pfor
  742.    else
  743.  
  744.    if tok = 'WHILE' then
  745.       pwhile
  746.    else
  747.  
  748.    if tok = 'WITH' then
  749.       pwith
  750.    else
  751.  
  752.    if tok = 'REPEAT' then
  753.       prepeat
  754.    else
  755.  
  756.    if tok = 'CASE' then
  757.       pcase
  758.    else
  759.  
  760.    if tok = 'IF' then
  761.       pif
  762.    else
  763.  
  764.    if tok = 'EXIT' then
  765.       pexit
  766.    else
  767.  
  768.    if tok = 'GOTO' then
  769.       pgoto
  770.    else
  771.  
  772.    if tok = 'HALT' then
  773.       phalt
  774.    else
  775.  
  776.    if tok = 'WRITE' then
  777.       pwrite
  778.    else
  779.  
  780.    if tok = 'WRITELN' then
  781.       pwrite
  782.    else
  783.  
  784.    if tok = 'READ' then
  785.       pread
  786.    else
  787.  
  788.    if tok = 'READLN' then
  789.       pread
  790.    else
  791.  
  792.    if tok = 'NEW' then
  793.       pnew
  794.    else
  795.  
  796.    if tok = 'PORT' then
  797.       pport('outportb')
  798.    else
  799.    if tok = 'PORTW' then
  800.       pport('outport')
  801.    else
  802.    if tok = 'MEM' then
  803.       pport('pokeb')
  804.    else
  805.    if tok = 'MEMW' then
  806.       pport('poke')
  807.    else
  808.  
  809.    if tok = 'INLINE' then
  810.       pinline
  811.    else
  812.  
  813.    if toktype = number then
  814.       pnumlabel
  815.    else
  816.  
  817.       pident;
  818. end;
  819.  
  820.  
  821. (********************************************************************)
  822. (*
  823.  * process begin...end blocks
  824.  *
  825.  * expects tok to be begin
  826.  * exits with tok = end
  827.  *
  828.  *)
  829.  
  830. procedure pblock;
  831. begin
  832.  
  833.    write(ofd[level],'{ ');
  834.    gettok;                 {get first token of first statement}
  835.  
  836.    while tok <> '}' do
  837.    begin
  838.       pstatement;                {process the statement}
  839.  
  840.       if tok = ';' then
  841.       begin
  842.          puttok;
  843.          gettok;              {get first token of next statement}
  844.       end;
  845.  
  846.    end;
  847.  
  848.    puttok;
  849.    gettok;
  850.    if tok = ';' then
  851.       gettok;
  852.  
  853. end;
  854.